﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Basic.Dto;
using LimaLims.Application.Service.Equipment.Dto;
using LimaLims.Application.Service.Role;
using LimaLims.Core;
using LimaLims.Core.Entity.Basic;
using LimaLims.Core.Entity.Equipment;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace LimaLims.Application.Service.Basic
{

    /// <summary>
    /// 产品分类服务
    /// </summary>
    [ApiDescriptionSettings(Name = "ProductCategory", Order = 155)]
    [Route("api")]
    public class ProductCategoryService : IProductCategoryService, IDynamicApiController, ITransient
    {
        private readonly IRepository<ProductCategory> _productCategoryRep;  // 设备仪器表仓储
        private readonly IRepository<Product> _productRep;  // 设备仪器表仓储
        private readonly IRepository<ProjectDrawing> _projectDrawingRep;  // 

        public ProductCategoryService(IRepository<ProductCategory> productCategoryRep, IRepository<Product> productRep, IRepository<ProjectDrawing> projectDrawingRep)
        {
            _productCategoryRep = productCategoryRep;
            _productRep = productRep;
            _projectDrawingRep = projectDrawingRep;
        }

        [HttpPost("productCategory/add")]
        public async Task Add(AddProductCategoryInput input)
        {
            var isExist = await _productCategoryRep.DetachedEntities.AnyAsync(u => u.ParentId == input.ParentId && u.Name == input.Name);
            if (isExist)
                throw Oops.Oh("同一层级分类已存在");
            var category = input.Adapt<ProductCategory>();
            category.Pids = await CreateNewPids(input.ParentId);
            await category.InsertAsync();
        }

        [HttpPost("productCategory/delete")]
        [UnitOfWork]
        public async Task Delete(long id)
        {
            var childIdList = await _productCategoryRep.DetachedEntities.Where(u => u.Pids.Contains(id.ToString()))
                                                               .Select(u => u.Id).ToListAsync();
            childIdList.Add(id);
            //判断是否包含产品
            var products = _productRep.DetachedEntities.Count(s => childIdList.Contains(s.CategoryId));

            if (products > 0)
            {
                throw Oops.Oh("此分类或者子级分类已有关联产品信息，请勿直接删除！");
            }

            //判断是否关联项目
            var projectDrawings = _projectDrawingRep.DetachedEntities.Count(s => childIdList.Contains(s.ProductCategoryId));

            if (projectDrawings > 0)
            {
                throw Oops.Oh("此分类或者子级分类已有关联项目图号信息，请勿直接删除！");
            }
            var articleCategorys = await _productCategoryRep.Where(u => childIdList.Contains(u.Id)).ToListAsync();
            await _productCategoryRep.DeleteAsync(articleCategorys);
        }

        [HttpPost("productCategory/edit")]
        public async Task Edit(EditProductCategoryInput input)
        {
            // Pid和Id不能一致，一致会导致无限递归
            if (input.Id == input.ParentId)
                throw Oops.Oh("父级分类不能为当前节点，请重新选择父级分类");
            var isExist = await _productCategoryRep.DetachedEntities.AnyAsync(u => u.ParentId == input.ParentId && u.Name == input.Name && u.Id != input.Id);
            if (isExist)
                throw Oops.Oh("同一层级分类已存在");
            // 如果是编辑，父id不能为自己的子节点
            var childIdList = await _productCategoryRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
                                                                .Select(u => u.Id).ToListAsync();
            if (childIdList.Contains(input.ParentId))
                throw Oops.Oh("父级分类不能为当前节点，请重新选择父级分类");

            var oldMenu = await _productCategoryRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == input.Id);
            // 生成新的pids
            var newPids = await CreateNewPids(input.ParentId);
            // 是否更新子节点的pids的标识
            var updateSubPidsFlag = false;
            // 父节点有变化
            if (input.ParentId != oldMenu.ParentId)
                updateSubPidsFlag = true;
            // 开始更新所有子节点的配置
            if (updateSubPidsFlag)
            {
                // 查找所有叶子节点，包含子节点的子节点
                var menuList = await _productCategoryRep.Where(u => EF.Functions.Like(u.Pids, $"%{oldMenu.Id}%")).ToListAsync();
                // 更新所有子节点的应用为当前分类的应用
                if (menuList.Count > 0)
                {
                    // 更新所有子节点的pids
                    if (updateSubPidsFlag)
                    {
                        menuList.ForEach(u =>
                        {
                            // 子节点pids组成 = 当前菜单新pids + 当前菜单id + 子节点自己的pids后缀
                            var oldParentCodesPrefix = oldMenu.Pids + "[" + oldMenu.Id + "],";
                            var oldParentCodesSuffix = u.Pids[oldParentCodesPrefix.Length..];
                            var menuParentCodes = newPids + "[" + oldMenu.Id + "]," + oldParentCodesSuffix;
                            u.Pids = menuParentCodes;
                        });
                        await _productCategoryRep.UpdateAsync(menuList);
                    }
                }
            }
            // 更新当前分类
            oldMenu = input.Adapt<ProductCategory>();
            oldMenu.Pids = newPids;
            await oldMenu.UpdateAsync(ignoreNullValues: true);
        }

        [HttpGet("productCategory/detail")]
        public async Task<ProductCategory> GetDetail(long id)
        {
            return await _productCategoryRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == id);
        }

        /// <summary>
        /// 菜单列表（树表）
        /// </summary>
        /// <returns></returns>
        [HttpGet("productCategory/list")]
        public async Task<dynamic> GetList()
        {
            var data = await _productCategoryRep.DetachedEntities.Include(s => s.PrintTemplate).OrderBy(u => u.Sort)
                                                          .ProjectToType<ProductCategoryListOutput>()
                                                          .ToListAsync();
            return new TreeBuildUtil<ProductCategoryListOutput>().Build(data);
        }

        /// <summary>
        /// 用于增加编辑下拉选项
        /// </summary>
        /// <returns></returns>
        [HttpGet("productCategory/tree")]
        public async Task<dynamic> TreeData()
        {
            var data = await _productCategoryRep.DetachedEntities.Where(u => u.ValidStatus).OrderBy(u => u.Sort)
               .Select(s => new ProductCategoryOutput
               {
                   Id = s.Id,
                   ParentId = s.ParentId.Value,
                   Name = s.Name,
               }).ToListAsync();

            return new TreeBuildUtil<ProductCategoryOutput>().Build(data);
        }

        /// <summary>
        /// 创建Pids格式
        /// 如果pid是0顶级节点，pids就是 [0];
        /// 如果pid不是顶级节点，pids就是 pid菜单的 pids + [pid] + ,
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        private async Task<string> CreateNewPids(long pid)
        {
            if (pid == 0L)
            {
                return "[0],";
            }
            else
            {
                var category = await _productCategoryRep.DetachedEntities.FirstOrDefaultAsync(u => u.Id == pid);
                return category.Pids + "[" + pid + "],";
            }
        }
    }
}
